48. Template Meta Programming(TMP)

TMP는 컴파일 타임에 실행되는 템플릿 기반의 프로그램을 작성하는 기법을 의미한다.
(C++ 컴파일러가 실행시키는 C++ 프로그램)

TMP를 이용하면,
TMP를 사용하지 않았을 때, 까다롭거나 불가능했던 코드를 만들 수 있으며,
기존에 런타임에 실행되던 계산을 컴파일 타임으로 전환할 수 있다.
(런타임 에러들을 컴파일 타임 도중에 찾을 수 있으며, 효율적으로 코드를 작성할 수 있다.)

TMP를 이용하면, 실행코드가 작아지고, 실행 시간이 짧아지며, 메모리도 적게 사용한다.
단, 컴파일 타임은 길어지게 됨

TMP는 자체로써 튜링 완전성을 갖고 있다고 알려져 있다.
(범용 프로그램과 동일하게 모든 계산을 수행할 수 있는 능력을 가지고 있음)

TMP로 작성된 코드는 기존의 C++ 구문과는 많이 다르다.
기존 C++의 if-else문은 TMP에서 템플릿-템플릿 특수화를 통해서 구현한다.
기존의 C++의 루프문(while)은 TMP에서 재귀함수(재귀식 템플릿 인스턴스화)를 통해서 구현한다.
#include <iostream>
// TMP factorial
template <unsigned n>
struct Factorial{
enum{ value=n*Factorial<n-1>::value };
};
template <> // (Factorial<0> )
struct Factorial<0>{
enum{ value=1 };
};
int main(void){
std::cout<<Factorial<5>::value<<std::endl;
std::cout<<Factorial<10>::value<<std::endl;
}; // ,
or constexpr
constexpr 함수는 C++14 이전에는
하나의 반환문만 포함할 수 있다.
C++14이후에는 지역변수를 사용할 수 있으며,
여러개의 반환문과 조건문을 사용할 수 있다.
// C++11/14
constexpr int factorial(int n){
return n<=1? 1: (n*factorial(n-1));
}
// only after C++14
constexpr int factorial(int n){
int result=0;
if(n<=1) result=1;
else result=n*factorial(n-1);
return result;
}
TMP가 유용하게 사용되는 영역
- 치수 단위(dimensional unit)의 정확성 확인
TMP를 이용하면, 프로그램 내에서 사용되는 모든 치수 단위의 조합이 옳바른지, 컴파일 타임에 확인할 수 있다.
early error detection(선행 에러 탐지)

- 행렬 연산의 최적화
표현식 템플릿(expression template)를 사용하면, 기존에 덩치 큰 임시 객체를 없앨 수 있으며,
루프까지 합칠 수 있다.

- 맞춤식 디자인 패턴 구현의 생성
전략(Strategy) 패턴, 감시자(Observer) 패턴, 방문자(Visitor) 패턴 등의 디자인 패턴은
TMP를 사용한 정책 기반 설계(policy-based desing)을 사용해서 설계상의 선택을 나타내는
템플릿을 만들 수 있다.
생성식 프로그래밍(generative programming)